package com.shlh.saas.util;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;

/**
 * Excel工具类
 */
@Component
public class ExcelUtils {

    private static final Logger log = LoggerFactory.getLogger(ExcelUtils.class);

    /**
     * 日期时间格式化器 - 中文习惯格式
     */
    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * 格式化字段值，特别处理日期时间类型
     *
     * @param value 原始值
     * @return 格式化后的字符串
     */
    private static String formatValue(Object value) {
        if (value == null) {
            return "";
        }

        // 特殊处理日期时间类型
        if (value instanceof Date) {
            synchronized (DATE_FORMAT) {
                String formattedDate = DATE_FORMAT.format((Date) value);
                return formattedDate;
            }
        }

        // 其他类型直接转换为字符串
        return String.valueOf(value);
    }

    /**
     * 导出Excel
     *
     * @param list      数据列表
     * @param sheetName sheet名称
     * @param clazz     实体类
     * @param fileName  文件名
     * @param response  HttpServletResponse
     * @throws IOException IO异常
     */
    public static <T> void exportExcel(List<T> list, String sheetName, String fileName, Class<T> clazz,
                                     HttpServletResponse response) throws IOException {
        exportExcel(list, sheetName, fileName, clazz, fileName, response);
    }

    /**
     * 导出Excel
     *
     * @param list      数据列表
     * @param sheetName sheet名称
     * @param title     标题
     * @param clazz     实体类
     * @param fileName  文件名
     * @param response  HttpServletResponse
     * @throws IOException IO异常
     */
    public static <T> void exportExcel(List<T> list, String sheetName, String title, Class<T> clazz, String fileName,
                                     HttpServletResponse response) throws IOException {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        // 添加跨域相关的响应头
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
        
        String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name()).replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + encodedFileName);
        
        // 自动调整列宽
        LongestMatchColumnWidthStyleStrategy columnWidthStyleStrategy = new LongestMatchColumnWidthStyleStrategy();
        
        EasyExcel.write(response.getOutputStream(), clazz)
                .sheet(sheetName)
                .registerWriteHandler(columnWidthStyleStrategy)
                .doWrite(list);
    }
    
    /**
     * 导出Excel，根据指定的列名和字段名
     *
     * @param response     HttpServletResponse
     * @param dataList     数据列表
     * @param fileName     文件名
     * @param columnNames  列名称数组
     * @param fields       字段名数组（与列名一一对应）
     * @throws IOException IO异常
     */
    public static void exportExcel(HttpServletResponse response, List<?> dataList, String fileName,
                                  String[] columnNames, String[] fields) throws IOException {
        if (dataList == null || dataList.isEmpty()) {
            throw new IllegalArgumentException("数据列表不能为空");
        }
        
        log.info("开始导出Excel，数据条数：{}，文件名：{}", dataList.size(), fileName);
        log.debug("列名：{}", Arrays.toString(columnNames));
        log.debug("字段名：{}", Arrays.toString(fields));
        
        // 使用前端能正确识别的Content-Type
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
        
        // 改进文件名编码处理，解决中文文件名问题
        String encodedFileName = URLEncoder.encode(fileName + ".xlsx", StandardCharsets.UTF_8.name())
            .replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + encodedFileName);
        
        // 将数据转换为List<List<String>>格式
        List<List<String>> dataRows = new ArrayList<>();
        for (Object data : dataList) {
            List<String> row = new ArrayList<>();
            for (String field : fields) {
                Object value = ReflectionUtils.getFieldValue(data, field);
                // 使用格式化方法处理值，特别是日期时间类型
                row.add(formatValue(value));
            }
            dataRows.add(row);
            if (dataRows.size() == 1) {
                log.debug("第一行数据示例：{}", row);
            }
        }
        
        try {
            // 创建表头
            List<List<String>> head = new ArrayList<>();
            for (String columnName : columnNames) {
                List<String> headColumn = new ArrayList<>();
                headColumn.add(columnName);
                head.add(headColumn);
            }
            
            // 使用自动列宽
            LongestMatchColumnWidthStyleStrategy columnWidthStyleStrategy = new LongestMatchColumnWidthStyleStrategy();
            
            // 写入数据
            EasyExcel.write(response.getOutputStream())
                    .head(head)
                    .sheet(fileName)
                    .registerWriteHandler(columnWidthStyleStrategy)
                    .doWrite(dataRows);
            
            log.info("Excel导出成功");
        } catch (Exception e) {
            log.error("导出Excel失败", e);
            throw new IOException("导出Excel失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 导入Excel文件
     *
     * @param file      MultipartFile文件
     * @param clazz     实体类Class
     * @param consumer  数据处理函数
     * @param <T>       实体类泛型
     * @throws IOException IO异常
     */
    public static <T> void importExcel(MultipartFile file, Class<T> clazz, Consumer<List<T>> consumer) throws IOException {
        List<T> dataList = new ArrayList<>();
        
        EasyExcel.read(file.getInputStream(), clazz, new AnalysisEventListener<T>() {
            @Override
            public void invoke(T data, AnalysisContext context) {
                dataList.add(data);
            }
            
            @Override
            public void doAfterAllAnalysed(AnalysisContext context) {
                consumer.accept(dataList);
            }
        }).sheet().doRead();
    }
    
    /**
     * 导入Excel文件并返回数据列表
     *
     * @param file  MultipartFile文件
     * @param clazz 实体类Class
     * @param <T>   实体类泛型
     * @return 数据列表
     * @throws IOException IO异常
     */
    public static <T> List<T> importExcel(MultipartFile file, Class<T> clazz) throws IOException {
        List<T> dataList = new ArrayList<>();
        
        EasyExcel.read(file.getInputStream(), clazz, new AnalysisEventListener<T>() {
            @Override
            public void invoke(T data, AnalysisContext context) {
                dataList.add(data);
            }
            
            @Override
            public void doAfterAllAnalysed(AnalysisContext context) {
                // 完成解析
            }
        }).sheet().doRead();
        
        return dataList;
    }
    
    /**
     * 将列名数组转换为EasyExcel需要的表头格式
     *
     * @param columnNames 列名数组
     * @return 处理后的表头列表
     */
    private static List<List<String>> convertToHead(String[] columnNames) {
        List<List<String>> head = new ArrayList<>();
        for (String columnName : columnNames) {
            List<String> headColumn = new ArrayList<>();
            headColumn.add(columnName);
            head.add(headColumn);
        }
        return head;
    }

    /**
     * 导出Excel，支持字段标红功能
     *
     * @param response        HttpServletResponse
     * @param dataList        数据列表
     * @param fileName        文件名
     * @param columnNames     列名称数组
     * @param fields          字段名数组（与列名一一对应）
     * @param highlightFields 需要标红的字段名数组
     * @throws IOException IO异常
     */
    public static void exportExcelWithHighlight(HttpServletResponse response, List<?> dataList, String fileName,
                                               String[] columnNames, String[] fields, String[] highlightFields) throws IOException {
        if (dataList == null || dataList.isEmpty()) {
            throw new IllegalArgumentException("数据列表不能为空");
        }

        log.info("开始导出带标红功能的Excel，数据条数：{}，文件名：{}", dataList.size(), fileName);
        log.debug("列名：{}", Arrays.toString(columnNames));
        log.debug("字段名：{}", Arrays.toString(fields));
        log.debug("标红字段：{}", Arrays.toString(highlightFields));

        // 设置响应头
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");

        String encodedFileName = URLEncoder.encode(fileName + ".xlsx", StandardCharsets.UTF_8.name())
            .replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + encodedFileName);

        try {
            // 创建工作簿
            Workbook workbook = new XSSFWorkbook();
            Sheet sheet = workbook.createSheet(fileName);

            // 创建样式
            CellStyle headerStyle = createHeaderStyle(workbook);
            CellStyle normalStyle = createNormalStyle(workbook);
            CellStyle highlightStyle = createHighlightStyle(workbook);

            // 创建表头行
            Row headerRow = sheet.createRow(0);
            for (int i = 0; i < columnNames.length; i++) {
                Cell cell = headerRow.createCell(i);
                cell.setCellValue(columnNames[i]);
                cell.setCellStyle(headerStyle);
            }

            // 确定哪些列需要标红
            Set<Integer> highlightColumnIndexes = new HashSet<>();
            if (highlightFields != null && highlightFields.length > 0) {
                for (String highlightField : highlightFields) {
                    for (int i = 0; i < fields.length; i++) {
                        if (fields[i].equals(highlightField)) {
                            highlightColumnIndexes.add(i);
                            break;
                        }
                    }
                }
            }

            log.info("标红列索引：{}", highlightColumnIndexes);

            // 填充数据行
            for (int rowIndex = 0; rowIndex < dataList.size(); rowIndex++) {
                Row dataRow = sheet.createRow(rowIndex + 1);
                Object data = dataList.get(rowIndex);

                for (int colIndex = 0; colIndex < fields.length; colIndex++) {
                    Cell cell = dataRow.createCell(colIndex);
                    Object value = ReflectionUtils.getFieldValue(data, fields[colIndex]);
                    // 使用格式化方法处理值，特别是日期时间类型
                    String cellValue = formatValue(value);
                    cell.setCellValue(cellValue);

                    // 应用样式：标红字段使用标红样式，其他使用普通样式
                    if (highlightColumnIndexes.contains(colIndex)) {
                        cell.setCellStyle(highlightStyle);
                    } else {
                        cell.setCellStyle(normalStyle);
                    }
                }
            }

            // 自动调整列宽
            for (int i = 0; i < columnNames.length; i++) {
                sheet.autoSizeColumn(i);
                // 设置最小列宽
                int currentWidth = sheet.getColumnWidth(i);
                if (currentWidth < 2000) {
                    sheet.setColumnWidth(i, 2000);
                }
            }

            // 写入响应流
            workbook.write(response.getOutputStream());
            workbook.close();

            log.info("带标红功能的Excel导出成功");
        } catch (Exception e) {
            log.error("导出带标红功能的Excel失败", e);
            throw new IOException("导出Excel失败: " + e.getMessage(), e);
        }
    }

    /**
     * 使用SXSSFWorkbook导出Excel（针对大数据量导出优化）
     * 该方法通过临时文件方式减少内存占用，避免直接写入响应流导致的超时问题
     */
    public static void exportExcelWithHighlightOptimized(HttpServletResponse response, List<?> dataList, String fileName,
                                             String[] columnNames, String[] fields, String[] highlightFields) throws IOException {
        
        if (dataList == null || dataList.isEmpty()) {
            throw new IllegalArgumentException("数据列表不能为空");
        }

        log.info("开始导出大数据量Excel(优化版)，数据条数：{}，文件名：{}", dataList.size(), fileName);
        log.debug("列名：{}", Arrays.toString(columnNames));
        log.debug("字段名：{}", Arrays.toString(fields));
        log.debug("标红字段：{}", Arrays.toString(highlightFields));

        // 创建临时文件
        File tempFile = File.createTempFile("export_", ".xlsx");
        log.info("创建临时文件: {}", tempFile.getAbsolutePath());

        try {
            // 使用SXSSFWorkbook代替XSSFWorkbook，减少内存占用
            SXSSFWorkbook workbook = new SXSSFWorkbook(100); // 窗口期100行
            Sheet sheet = workbook.createSheet("数据");

            // 创建样式
            CellStyle headerStyle = createHeaderStyle(workbook);
            CellStyle normalStyle = createNormalStyle(workbook);
            CellStyle highlightStyle = createHighlightStyle(workbook);

            // 创建表头行
            Row headerRow = sheet.createRow(0);
            for (int i = 0; i < columnNames.length; i++) {
                Cell cell = headerRow.createCell(i);
                cell.setCellValue(columnNames[i]);
                cell.setCellStyle(headerStyle);
            }

            // 确定哪些列需要标红
            Set<Integer> highlightColumnIndexes = new HashSet<>();
            if (highlightFields != null && highlightFields.length > 0) {
                for (String highlightField : highlightFields) {
                    for (int i = 0; i < fields.length; i++) {
                        if (fields[i].equals(highlightField)) {
                            highlightColumnIndexes.add(i);
                            break;
                        }
                    }
                }
            }

            log.info("标红列索引：{}", highlightColumnIndexes);

            // 填充数据行
            int batchSize = 1000;
            for (int rowIndex = 0; rowIndex < dataList.size(); rowIndex++) {
                Row dataRow = sheet.createRow(rowIndex + 1);
                Object data = dataList.get(rowIndex);

                for (int colIndex = 0; colIndex < fields.length; colIndex++) {
                    Cell cell = dataRow.createCell(colIndex);
                    Object value = ReflectionUtils.getFieldValue(data, fields[colIndex]);
                    // 使用格式化方法处理值，特别是日期时间类型
                    String cellValue = formatValue(value);
                    cell.setCellValue(cellValue);

                    // 应用样式：标红字段使用标红样式，其他使用普通样式
                    if (highlightColumnIndexes.contains(colIndex)) {
                        cell.setCellStyle(highlightStyle);
                    } else {
                        cell.setCellStyle(normalStyle);
                    }
                }
                
                // 每处理1000行记录一次进度
                if ((rowIndex + 1) % batchSize == 0) {
                    log.debug("已处理 {} 行数据，总计 {} 行", rowIndex + 1, dataList.size());
                }
            }

            // 自动调整列宽（仅对可见行）
            for (int i = 0; i < columnNames.length; i++) {
                sheet.setColumnWidth(i, 4000); // 设置固定列宽
            }

            log.info("数据填充完成，开始写入临时文件");

            // 先写入临时文件
            try (FileOutputStream fileOut = new FileOutputStream(tempFile)) {
                workbook.write(fileOut);
            }
            
            // 清理临时文件
            workbook.dispose();
            
            log.info("临时文件写入完成，文件大小: {} 字节", tempFile.length());

            // 设置响应头
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            
            String encodedFileName = URLEncoder.encode(fileName + ".xlsx", StandardCharsets.UTF_8.name())
                .replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + encodedFileName);
            response.setHeader("Content-Length", String.valueOf(tempFile.length()));
            response.setHeader("Connection", "Keep-Alive");
            response.setHeader("Keep-Alive", "timeout=600");
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            
            log.info("开始传输临时文件到客户端");

            // 从临时文件传输到响应流 - 使用分块传输，定期刷新流
            try (FileInputStream fileIn = new FileInputStream(tempFile);
                 OutputStream out = response.getOutputStream()) {
                
                byte[] buffer = new byte[4096]; // 降至4K缓冲区
                int bytesRead;
                long totalBytes = 0;
                long lastFlushTime = System.currentTimeMillis();
                int flushInterval = 250; // 每250ms刷新一次
                
                while ((bytesRead = fileIn.read(buffer)) != -1) {
                    out.write(buffer, 0, bytesRead);
                    totalBytes += bytesRead;
                    
                    // 基于时间间隔和大小阈值的双重刷新策略
                    long currentTime = System.currentTimeMillis();
                    if (totalBytes % (256 * 1024) == 0 || // 每256KB刷新一次 
                        (currentTime - lastFlushTime) > flushInterval) { 
                        try {
                            out.flush();
                            lastFlushTime = currentTime;
                            
                            if (totalBytes % (1024 * 1024) == 0) { // 每传输1MB记录一次
                                log.debug("已传输 {} MB", totalBytes / (1024 * 1024));
                            }
                        } catch (Exception e) {
                            log.warn("刷新响应流时出错，可能是客户端已断开连接", e);
                            break;
                        }
                    }
                }
                
                try {
                    out.flush();
                    log.info("文件传输完成，总计传输 {} 字节", totalBytes);
                } catch (Exception e) {
                    log.warn("最终刷新响应流时出错，可能是客户端已断开连接", e);
                }
            } catch (IOException e) {
                // 特殊处理ClientAbortException，它通常表示客户端断开连接，不是服务器错误
                if (e instanceof org.apache.catalina.connector.ClientAbortException) {
                    log.warn("客户端中断连接，文件传输被取消: {}", e.getMessage());
                } else {
                    // 其他IO异常需要重新抛出
                    throw e;
                }
            }

            log.info("大数据量Excel导出成功(优化版)");
        } catch (Exception e) {
            log.error("导出大数据量Excel失败(优化版)", e);
            throw new IOException("导出Excel失败: " + e.getMessage(), e);
        } finally {
            // 确保删除临时文件
            if (tempFile.exists() && !tempFile.delete()) {
                tempFile.deleteOnExit();
                log.warn("临时文件无法立即删除，已标记为JVM退出时删除: {}", tempFile.getAbsolutePath());
            } else {
                log.info("临时文件已删除: {}", tempFile.getAbsolutePath());
            }
        }
    }

    /**
     * 优化的Excel导出方法，使用SXSSFWorkbook处理大数据量，适用于5万+数据量
     * 
     * @param response HttpServletResponse
     * @param dataList 数据列表
     * @param fileName 文件名(不含扩展名)
     * @param columnNames 列名
     * @param fields 字段名
     * @throws IOException IO异常
     */
    public static void exportExcelOptimized(HttpServletResponse response, List<?> dataList, 
                                        String fileName, String[] columnNames, String[] fields) throws IOException {
        if (dataList == null || dataList.isEmpty()) {
            throw new IllegalArgumentException("数据列表不能为空");
        }
        
        log.info("开始优化导出Excel，数据条数：{}，文件名：{}", dataList.size(), fileName);
        
        // 使用SXSSFWorkbook处理大数据量，设置内存中保留100行
        SXSSFWorkbook workbook = new SXSSFWorkbook(100);
        // 创建临时文件
        File tempFile = null;
        
        try {
            // 创建Sheet
            Sheet sheet = workbook.createSheet(fileName);
            
            // 创建表头样式
            CellStyle headerStyle = workbook.createCellStyle();
            headerStyle.setAlignment(HorizontalAlignment.CENTER);
            headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
            headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            headerStyle.setBorderBottom(BorderStyle.THIN);
            headerStyle.setBorderLeft(BorderStyle.THIN);
            headerStyle.setBorderRight(BorderStyle.THIN);
            headerStyle.setBorderTop(BorderStyle.THIN);
            
            Font headerFont = workbook.createFont();
            headerFont.setBold(true);
            headerStyle.setFont(headerFont);
            
            // 创建表头行
            Row headerRow = sheet.createRow(0);
            for (int i = 0; i < columnNames.length; i++) {
                Cell cell = headerRow.createCell(i);
                cell.setCellValue(columnNames[i]);
                cell.setCellStyle(headerStyle);
                // 设置列宽，不再使用自动调整大小以提高性能
                sheet.setColumnWidth(i, 4000);
            }
            
            // 创建数据行
            int rowIndex = 1;
            int batchSize = 1000; // 每1000行记录日志一次
            long startTime = System.currentTimeMillis();
            
            for (Object data : dataList) {
                Row row = sheet.createRow(rowIndex++);
                
                for (int i = 0; i < fields.length; i++) {
                    Cell cell = row.createCell(i);
                    Object value = ReflectionUtils.getFieldValue(data, fields[i]);
                    String formattedValue = formatValue(value);
                    cell.setCellValue(formattedValue);
                }
                
                // 每处理1000行打印一次进度日志
                if (rowIndex % batchSize == 0) {
                    log.info("已处理 {} 行数据，耗时：{}ms", rowIndex - 1, 
                          System.currentTimeMillis() - startTime);
                }
            }
            
            // 创建临时文件
            tempFile = File.createTempFile("excel_export_", ".xlsx");
            try (FileOutputStream fos = new FileOutputStream(tempFile)) {
                workbook.write(fos);
            }
            
            // 设置响应头
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            response.setHeader("Connection", "Keep-Alive");
            response.setHeader("Proxy-Connection", "Keep-Alive");
            
            // 设置文件名
            String encodedFileName = URLEncoder.encode(fileName + ".xlsx", StandardCharsets.UTF_8.name())
                .replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + encodedFileName);
            
            // 设置Content-Length头，告诉浏览器文件大小
            response.setContentLength((int) tempFile.length());
            
            // 流式传输文件内容到客户端
            try (FileInputStream fis = new FileInputStream(tempFile);
                 OutputStream os = response.getOutputStream()) {
                
                byte[] buffer = new byte[4096];
                int bytesRead;
                long totalBytesRead = 0;
                long fileSize = tempFile.length();
                long lastLogTime = System.currentTimeMillis();
                
                while ((bytesRead = fis.read(buffer)) != -1) {
                    os.write(buffer, 0, bytesRead);
                    
                    // 每隔256KB刷新输出流，保持连接活跃
                    totalBytesRead += bytesRead;
                    if (totalBytesRead % (256 * 1024) == 0) {
                        os.flush();
                    }
                    
                    // 每秒记录一次进度
                    long currentTime = System.currentTimeMillis();
                    if (currentTime - lastLogTime > 1000) {
                        log.info("文件传输进度：{}/{}字节 ({}%)", 
                              totalBytesRead, fileSize, totalBytesRead * 100 / fileSize);
                        lastLogTime = currentTime;
                    }
                }
                
                // 最后一次刷新
                os.flush();
                log.info("Excel文件传输完成，总大小：{}字节", totalBytesRead);
            }
            
            log.info("Excel导出成功，总耗时：{}ms", System.currentTimeMillis() - startTime);
            
        } catch (Exception e) {
            log.error("导出Excel失败", e);
            throw new IOException("导出Excel失败: " + e.getMessage(), e);
        } finally {
            // 清理临时文件
            if (tempFile != null && tempFile.exists()) {
                boolean deleted = tempFile.delete();
                if (!deleted) {
                    log.warn("临时文件删除失败: {}", tempFile.getAbsolutePath());
                    // 注册JVM关闭时删除
                    tempFile.deleteOnExit();
                }
            }
            
            // 清理临时文件
            workbook.dispose();
            try {
                workbook.close();
            } catch (IOException e) {
                log.warn("关闭工作簿失败", e);
            }
        }
    }

    /**
     * 创建表头样式
     */
    private static CellStyle createHeaderStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        Font font = workbook.createFont();

        // 设置字体
        font.setBold(true);
        font.setFontHeightInPoints((short) 12);
        font.setColor(IndexedColors.WHITE.getIndex());

        // 设置样式
        style.setFont(font);
        style.setFillForegroundColor(IndexedColors.DARK_BLUE.getIndex());
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);

        // 设置边框
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);

        return style;
    }

    /**
     * 创建普通单元格样式
     */
    private static CellStyle createNormalStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        Font font = workbook.createFont();

        font.setFontHeightInPoints((short) 11);
        font.setColor(IndexedColors.BLACK.getIndex());

        style.setFont(font);
        style.setAlignment(HorizontalAlignment.LEFT);
        style.setVerticalAlignment(VerticalAlignment.CENTER);

        // 设置边框
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);

        return style;
    }

    /**
     * 创建标红单元格样式
     */
    private static CellStyle createHighlightStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        Font font = workbook.createFont();

        // 设置红色字体
        font.setFontHeightInPoints((short) 11);
        font.setColor(IndexedColors.RED.getIndex());
        font.setBold(true);

        style.setFont(font);
        style.setAlignment(HorizontalAlignment.LEFT);
        style.setVerticalAlignment(VerticalAlignment.CENTER);

        // 设置淡红色背景
        style.setFillForegroundColor(IndexedColors.ROSE.getIndex());
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);

        // 设置边框
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);

        return style;
    }
}